package com.tour.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mysql.jdbc.StringUtils;
import com.tour.client.MyClient;
import com.tour.config.ResponseWrapper;
import com.tour.entity.Scenic;
import com.tour.mapper.ScenicMapper;
import com.tour.service.ScenicService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tour.utils.PageUtil;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.GeoOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author lel
 * @since 2021-01-18
 */
@Service
public class ScenicServiceImpl extends ServiceImpl<ScenicMapper, Scenic> implements ScenicService {

    @Value("${prop.upload-folder}")
    private String setPath;
    /**
     * 上传路径
     */
    private String uploadPath;
    /**
     * 返回路径
     */
    private String resPath;

    @Autowired
    ScenicMapper scenicMapper;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    MyClient myClient;

    public ResponseWrapper addScenic(Scenic scenic){
        if (scenic != null){
            int result = scenicMapper.insert(scenic);
            if (result == 1){
                return ResponseWrapper.markCustom(true,200,"增加景区成功",null);
            }else {
                return ResponseWrapper.markError();
            }
        }else {
            return ResponseWrapper.markError();
        }
    }
    public ResponseWrapper updateScenic(Scenic scenic){
        if (scenic != null){
            int result = scenicMapper.updateById(scenic);
            if (result == 1){
                return ResponseWrapper.markCustom(true,200,"修改景区成功",null);
            }else {
                return ResponseWrapper.markError();
            }
        }else {
            return ResponseWrapper.markError();
        }
    }

    @Scheduled(cron = "0 0 0/2 * * ?")
    public ResponseWrapper updateWeather(){
        List<Scenic> scenicList = scenicMapper.selectList(null);
        for (Scenic scenic :scenicList){
            String localtion = scenic.getScenicLongitude()+","+scenic.getScenicLatitude();
            System.out.println(localtion);
            Map weather = myClient.getWeather(localtion);
            Map result = (Map) weather.get("result");
            Map realtime = (Map) result.get("realtime");
            String temperature = realtime.get("temperature").toString();
            String skycon = realtime.get("skycon").toString();
            String skycons = null;
            if (skycon.equals("CLEAR_DAY")){
                skycons="晴（白天）";
            }else if (skycon.equals("CLEAR_NIGHT")){
                skycons="晴（夜间）";
            }
            else if (skycon.equals("PARTLY_CLOUDY_DAY")){
                skycons="多云（白天）";
            }
            else if (skycon.equals("PARTLY_CLOUDY_NIGHT")){
                skycons="多云（夜间）";
            }
            else if (skycon.equals("CLOUDY")){
                skycons="阴";
            }
            else if (skycon.equals("LIGHT_HAZE")){
                skycons="轻度雾霾";
            }
            else  if (skycon.equals("MODERATE_HAZE")){
                skycons="中度雾霾";
            }
            else if (skycon.equals("HEAVY_HAZE")){
                skycons="重度雾霾";
            }
            else if (skycon.equals("LIGHT_RAIN")){
                skycons="小雨";
            }
            else if (skycon.equals("MODERATE_RAIN")){
                skycons="中雨";
            }
            else  if (skycon.equals("HEAVY_RAIN")){
                skycons="大雨";
            }
            else if (skycon.equals("STORM_RAIN")){
                skycons="暴雨";
            }
            else if (skycon.equals("FOG")){
                skycons="雾";
            }
            else if (skycon.equals("LIGHT_SNOW")){
                skycons="小雪";
            }
            else  if (skycon.equals("MODERATE_SNOW")){
                skycons="中雪";
            }
            else  if (skycon.equals("HEAVY_SNOW")){
                skycons="大雪";
            }
            else  if (skycon.equals("STORM_SNOW")){
                skycons="暴雪";
            }
            else if (skycon.equals("DUST")){
                skycons="浮尘";
            }
            else  if (skycon.equals("SAND")){
                skycons="沙尘";
            }
            else if (skycon.equals("WIND")){
                skycons="大风";
            }
            String weathers = temperature.substring(0,temperature.indexOf(".")) + "°C "+skycons;
            scenic.setWeather(weathers);
            scenicMapper.updateById(scenic);
        }
        return null;
    }

    public ResponseWrapper deleteScenic(Integer scenicId){
        if (scenicId != null){
            int result = scenicMapper.deleteById(scenicId);
            if (result == 1 ){
                return ResponseWrapper.markCustom(true,200,"删除景区成功",null);
            }else {
                return ResponseWrapper.markError();
            }
        }else {
            return ResponseWrapper.markError();
        }
    }

    public ResponseWrapper findScenicById(Integer scenicId){
        if (scenicId != null){
            Scenic scenic = scenicMapper.selectById(scenicId);
            Integer reading = scenic.getReading();
            String read = String.valueOf(reading);
            String ScenicKey = String.valueOf(scenicId);
            redisTemplate.opsForValue().set(ScenicKey,read);
            stringRedisTemplate.opsForValue().increment(ScenicKey,1);
            int count = Integer.parseInt(stringRedisTemplate.boundValueOps(ScenicKey).get(0,-1));
            scenic.setReading(count);
            scenicMapper.updateById(scenic);
            ResponseWrapper wrapper = ResponseWrapper.markSuccess(scenic);
            wrapper.getData().put("data",scenic);
            return wrapper;
        }else {
            return ResponseWrapper.markError();
        }
    }
    
    public ResponseWrapper findScenicByRead(Integer pageSize,Integer pageNum,String city){
        QueryWrapper<Scenic> scenicQueryWrapper = new QueryWrapper<>();
        scenicQueryWrapper.eq(!StringUtils.isNullOrEmpty(city),"city",city).orderByDesc("reading");
        Page<Scenic> page = new Page<>(pageNum,pageSize);
        IPage<Scenic> iPage = scenicMapper.selectPage(page,scenicQueryWrapper);
        List<Scenic> scenics = iPage.getRecords();
        ResponseWrapper wrapper = ResponseWrapper.markSuccess(scenics);
        wrapper.getData().put("data",scenics);
        wrapper.getData().put("total",page.getTotal());
        wrapper.getData().put("pageNum",page.getCurrent());
        wrapper.getData().put("pageSize",page.getSize());
        return wrapper;
    }

    public ResponseWrapper findScenicByDistance(Integer userId,Double mylongitude,Double mylatitude,Integer pageSize,Integer pageNum,String city){
        QueryWrapper<Scenic> scenicQueryWrapper = new QueryWrapper<>();
        scenicQueryWrapper.eq(!StringUtils.isNullOrEmpty(city),"city",city);
        List<Scenic> scenics = scenicMapper.selectList(scenicQueryWrapper);
        GeoOperations geoOperations = redisTemplate.opsForGeo();
        //首先存入客户端上传的经纬度和指定地点的经纬度
        Map<String,Object> map = new HashMap<>();
        String id = String.valueOf(userId+"scenic");
        for (int i = 0; i<scenics.size() ; i ++   ){
            String scenicid =String.valueOf(scenics.get(i).getScenicId());
            Double latitude = Double.valueOf(scenics.get(i).getScenicLatitude()).doubleValue() ;
            Double longitude =Double.valueOf(scenics.get(i).getScenicLongitude()).doubleValue();
            map.put("scenic",new Point(longitude,latitude));
            map.put("me",new Point(mylongitude ,mylatitude));
            // 将这些地址数据保存到redis中
            geoOperations.geoAdd("GET_DISTANCE",map);
            // 调用方法,计算北京西站与北京南站之间的距离;
            double value = geoOperations.geoDist("GET_DISTANCE", "scenic", "me", RedisGeoCommands.DistanceUnit.KILOMETERS).getValue();
            redisTemplate.opsForZSet().add(id,scenicid,value);

        }
        //set转list
        Set<String> stringSet = redisTemplate.opsForZSet().range(id, 0,-1);
        List<String> result = new ArrayList<>(stringSet);
        List<Integer> codesInteger = result.stream().map(Integer::parseInt).collect(Collectors.toList());
        ArrayList<Scenic> scenicArrayList = new ArrayList<>();
        for(Integer i :codesInteger ){
            Scenic scenic = scenicMapper.selectById(i);
            scenicArrayList.add(scenic);
        }
        List<Scenic> scenicList = PageUtil.startPage(scenicArrayList,pageNum,pageSize);
        ResponseWrapper wrapper = ResponseWrapper.markSuccess(scenicList);
        wrapper.getData().put("data",scenicList);
        return wrapper;
    }

    public <StageDTO> ResponseWrapper findNearScenic(Integer scenicId){
        Scenic scenic = scenicMapper.selectById(scenicId);
        List<Scenic> scenics = scenicMapper.selectList(null);
        GeoOperations geoOperations = redisTemplate.opsForGeo();
        //首先存入客户端上传的经纬度和指定地点的经纬度
        Map<String,Object> map = new HashMap<>();
        for (int i = 0; i<scenics.size() ; i ++   ){
            String scenicid =String.valueOf(scenics.get(i).getScenicId());
            Double latitude = Double.valueOf(scenics.get(i).getScenicLatitude()).doubleValue() ;
            Double longitude =Double.valueOf(scenics.get(i).getScenicLongitude()).doubleValue();
            map.put(scenicid,new Point(longitude,latitude));
            // 将这些地址数据保存到redis中
            geoOperations.geoAdd("GET_DISTANCE",map);
        }
        Point point = new Point(Double.valueOf(scenic.getScenicLongitude()), Double.valueOf(scenic.getScenicLatitude()));
        Metric metric = RedisGeoCommands.DistanceUnit.KILOMETERS;
        Distance distance = new Distance(30, metric);

        Circle circle = new Circle(point, distance);
        RedisGeoCommands.GeoRadiusCommandArgs geoRadiusCommandArgs = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().limit(3);
        System.out.println("----");
        redisTemplate.opsForGeo().radius("GET_DISTANCE",circle,geoRadiusCommandArgs);
        GeoResults<RedisGeoCommands.GeoLocation<String>> radius = redisTemplate.opsForGeo()
                .radius("GET_DISTANCE", circle, geoRadiusCommandArgs);
        ArrayList<Scenic> scenicArrayList = new ArrayList<>();
        if (radius != null) {
            List<StageDTO> stageDTOS = new ArrayList<>();
            radius.forEach(geoLocationGeoResult -> {
                RedisGeoCommands.GeoLocation<String> content = geoLocationGeoResult.getContent();
                //member 名称  如  tianjin
                String name = content.getName();
                Scenic sceniclist = scenicMapper.selectById(name);
                scenicArrayList.add(sceniclist);
            });
        }
        ResponseWrapper wrapper = ResponseWrapper.markSuccess(scenicArrayList);
        wrapper.getData().put("data",scenicArrayList);
        return wrapper;
    }

    public ResponseWrapper findScenicBySearch(String scenicName,Integer pageNum,Integer pageSize){
        QueryWrapper<Scenic> scenicQueryWrapper = new QueryWrapper<>();
        scenicQueryWrapper.like("scenic_name",scenicName);
        Page<Scenic> scenicPage = new Page<>(pageNum,pageSize);
        IPage<Scenic> iPage =scenicMapper.selectPage(scenicPage,scenicQueryWrapper);
        List<Scenic> scenics = iPage.getRecords();
        ResponseWrapper wrapper = ResponseWrapper.markSuccess(scenics);
        wrapper.getData().put("data",scenics);
        wrapper.getData().put("total",scenicPage.getTotal());
        wrapper.getData().put("pageNum",scenicPage.getCurrent());
        wrapper.getData().put("pageSize",scenicPage.getSize());
        return wrapper;
    }



    public ResponseWrapper picUpload(MultipartFile file) throws IOException {
        /*文件存放位置*/
        String picPath = "/picture/";
        uploadPath = setPath + picPath;
        /*返回文件路径*/
        resPath = picPath;
        /*获取文件数组*/
        ArrayList<String> list = getFile(uploadPath);
        if (file.isEmpty()) {
            return ResponseWrapper.markCustom(false,400,"上传失败",null);
        }else {
            /*获取文件名*/
            String getFileName = file.getOriginalFilename();
            BufferedImage bi = ImageIO.read(file.getInputStream());
            if (bi != null){
                String fileName = null;
                File saveFile;
                if (list.size() == 0) {
                    /*创建文件*/
                    saveFile = new File(uploadPath, getFileName);
                } else {
                    /*遍历所有文件夹，判断是否重名*/
                    fileName = checkFileName(list, getFileName,0);
                    /*创建文件*/
                    saveFile = new File(uploadPath, fileName);
                }
                if (fileName == null){
                    fileName= getFileName;
                }
                //判断文件父目录是否存在
                if (!saveFile.getParentFile().exists()) {
                    saveFile.getParentFile().mkdirs();
                    System.out.println(saveFile.getParentFile().getAbsolutePath());
                }
                try {
                    //压缩图片后保存
                    Thumbnails.of(file.getInputStream()).scale(0.5f)
                            .toFile(saveFile.getPath());
                    String url = "http://111.75.252.147:8888/picture/"+fileName;
                    ResponseWrapper wrapper = ResponseWrapper.markSuccess(url);
                    wrapper.getData().put("url",url);
                    return wrapper;
                } catch (IllegalStateException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    return ResponseWrapper.markCustom(false,400,"上传失败",null);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    return ResponseWrapper.markCustom(false,400,"上传失败",null);
                }
            }else {
                return ResponseWrapper.markError();
            }

        }

    }
    /**
     * @param names 文件下文件名的集合
     * @param name  存入的文件名
     * @param index 索引的开始位置
     * @return 符合要求的文件名
     */
    private static String checkFileName(ArrayList<String> names, String name, int index) {
        String indexName;
        if (index == 0 ) {
            indexName = name;
        } else {
            indexName = name.substring(0, name.indexOf(".")) + "(" + index + ")" +name.substring(name.indexOf("."));
        }
        if (names.contains(indexName)) {
            index +=1;
            name = checkFileName(names, name, index);
        } else {
            return indexName;
        }
        return name;
    }

    /**
     * @param path 需要遍历的路径
     * @return 路径下文件的名称集合
     */
    private static ArrayList<String> getFile(String path) {
        // 获得指定文件对象
        File file = new File(path);
        // 获得该文件夹内的所有文件
        File[] array = file.listFiles();
        ArrayList<String> list = new ArrayList<>();
        if (array != null) {
            for (File value : array) {
                list.add(value.getName());
            }
        }
        return list;
    }

}
